package com.geovis.boot.exception.base;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

/**
 * 异常类
 * Created by l.wang on 2018年8月22日
 */
@Slf4j
//@ControllerAdvice
//@SuppressWarnings("deprecation")
public class BaseResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
	protected ErrorResponseFactory errorResponseFactory;
	
	public BaseResponseEntityExceptionHandler(ErrorResponseFactory errorResponseFactory) {
        this.errorResponseFactory = errorResponseFactory;
    }
	
	@Override
    protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_HTTP_REQUEST_METHOD_NOT_SUPPORTED_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_HTTP_MEDIA_TYPE_NOT_SUPPORTED_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_HTTP_MEDIA_TYPE_NOT_ACCEPTABLE_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_MISSING_PATH_VARIABLE_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_MISSING_SERVLET_REQUEST_PARAMETER_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_SERVLET_REQUEST_BINDING_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_CONVERSION_NOT_SUPPORTED_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_HTTP_MESSAGE_NOT_READABLE_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_HTTP_MESSAGE_NOT_WRITABLE_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_MISSING_SERVLET_REQUEST_PART_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_NO_HANDLER_FOUND_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
//        BindingResult result = ex.getBindingResult();
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_BIND_ERROR, request.getLocale());
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        BindingResult result = ex.getBindingResult();
        ErrorResponse bodyOfResponse = ErrorResponse.of(
                ErrorMap.ERROR_ALL_CLIENT_METHOD_ARGUMENT_NOT_VALID_ERROR,
//                "invalid arguments",
                result.getAllErrors().toString()
        );
        return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), status, request);
    }

    @Override
    protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(
                ErrorMap.ERROR_ALL_CLIENT_TYPE_MISMATCH_ERROR, request.getLocale());
        return new ResponseEntity<>(bodyOfResponse, new HttpHeaders(), status);
    }



//    @ExceptionHandler(value = {RateLimitExceededException.class})
//    public ResponseEntity<Object> handlerRateLimitExceededException(RateLimitExceededException ex, WebRequest request) {
//
//        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(ErrorMap.
//                ERROR_ALL_CLIENT_RATE_LIMIT_EXCEEDED_ERROR, request.getLocale(), ex.getMessage());
//        return new ResponseEntity<>(bodyOfResponse, new HttpHeaders(), HttpStatus.TOO_MANY_REQUESTS);
//    }
//
//    @ExceptionHandler(value = {TimesLimitExceededException.class})
//    public ResponseEntity<Object> handlerTimesLimitExceededException(TimesLimitExceededException ex, WebRequest request) {
//
//        ErrorResponse bodyOfResponse = errorResponseFactory.getErrorResponse(ErrorMap.
//                ERROR_ALL_CLIENT_TIMES_LIMIT_EXCEEDED_ERROR, request.getLocale(), ex.getMessage());
//        return new ResponseEntity<>(bodyOfResponse, new HttpHeaders(), HttpStatus.TOO_MANY_REQUESTS);
//    }
	
}
